const UglifyJS = require('uglify-es'),
  fs = require('fs'),
  path = require('path');

const config = {
  entry: './src',
  output: './dist',
  ignore: [
    './node_modules',
    './dist',
    './index.js',
    './package.json',
    './package-lock.json',
  ],
  options: {
    // 解析配置
    parse: {},
    // 压缩配置
    compress: {
      drop_console: true,
    },
    // 混淆配置
    mangle: {},
    // 输出配置
    output: {
      comments: false,    // 移除注释
    },
    sourceMap: {},
    ecma: 8,  // specify one of: 5, 6, 7 or 8
    keep_fnames: false,   // 防止丢弃或损坏函数名
    keep_classnames: false,
    toplevel: true,    // 混淆最高作用域中的变量和函数名
    warnings: false,
  }
}

const handle = (src, dist) => {
  // 解析一个目录，遍历目录下一级所有资源
  //   若是目录则继续解析，
  //   若是文件则判断压缩或者复制
  let paths = fs.readdirSync(src); //查询当前目录下内容
  paths.forEach (p => {
    // 解析输入、输出路径
    let full_src = path.resolve(src, p);
    let full_dist = path.resolve(dist, p);
    // console.log(`>${p}: ${full_src} --> ${full_dist}`)

    // 判断 ignore
    if (checkIgnore(full_src, p)) return console.log('忽略：', p);

    fs.stat(full_src, (err, stats) => {
      if (err) throw err;
      if (stats.isFile()) {
        // 文件
        if (/.js$/.test(full_src)) {
          console.log('正在压缩js：' + full_src)
          let code = fs.readFileSync(full_src, "utf8");
          let result = UglifyJS.minify(code, config.options);
          fs.writeFileSync(full_dist, result.code)
        } else {
          let readable = fs.createReadStream(full_src);
          let writable = fs.createWriteStream(full_dist);
          readable.pipe(writable);
        }
      } else if (stats.isDirectory()) { 
        //目录 递归
        checkDirectory(full_src, full_dist, handle);
      }
    });
  });
}
const checkDirectory = (src, dist, callback) => {
  // 查询输出目录
  fs.access(dist, fs.constants.F_OK, (err) => {
    if (err) {
      // 不存在此目录，则创建
      fs.mkdirSync(dist);
      // 随后执行目录解析操作
      callback(src, dist);
    } else {
      callback(src, dist);
    }
  });
};

const checkIgnore = (src, full_path) => {
  let ignoreList = config.ignore.map(i => path.resolve(config.entry, i))
  if (ignoreList.indexOf(src) >= 0) return true;
  if (full_path.indexOf('.') === 0) return true;
  if (/\.md$/.test(full_path)) return true;
}

const delPath = (url, isRoot = false) => {
  if (/^(\/)|^(\.\.\/)|^(\.\/)$/.test(url)) {
    console.warn("发现危险操作");
    throw new Error("发现危险操作..");
  }
  url = path.resolve(url)
  if (!fs.existsSync(url)) {
    console.warn("路径不存在");
    return "路径不存在";
  }
  let info = fs.statSync(url);
  if (info.isDirectory()) { 
    //目录
    let paths = fs.readdirSync(url);
    // console.log(paths)
    if (paths.length > 0) {
      for (let i = 0; i < paths.length; i++) {
        delPath(`${url}/${paths[i]}`); 
        if (i == paths.length - 1 && !isRoot) { 
          //删掉当前目录
          delPath(`${url}`);
        }
      }
    } else { 
      //删除空目录
      !isRoot && fs.rmdirSync(url),console.log('删除目录：', url)
    }
  } else if (info.isFile()) {
    //删除文件
    fs.unlinkSync(url); 
    // console.log('删除：', url)
  }
}

// 执行
delPath(config.output, true)
checkDirectory(config.entry, config.output, handle);